import * as monaco from "monaco-editor";
import EditorWorker from 'monaco-editor/esm/vs/editor/editor.worker.js?worker';
import JsonWorker from 'monaco-editor/esm/vs/language/json/json.worker.js?worker';
import CssWorker from 'monaco-editor/esm/vs/language/css/css.worker.js?worker';
import TsWorker from 'monaco-editor/esm/vs/language/typescript/ts.worker.js?worker';

self.MonacoEnvironment = {

    getWorker: function (moduleId, label) {
        if (label === 'json') {
            return new JsonWorker();
        }
        if (label === 'css' || label === 'scss' || label === 'less') {
            return new CssWorker();
        }
        if (label === 'typescript' || label === 'javascript') {
            return new TsWorker();
        }
        return new EditorWorker();
    }
};

// PostgreSQL 常用关键字
const pgKeywords = [
    // 基础 DML
    'SELECT', 'FROM', 'WHERE', 'GROUP BY', 'ORDER BY', 'HAVING', 'LIMIT', 'OFFSET',
    'INSERT', 'INTO', 'VALUES', 'UPDATE', 'SET', 'DELETE',

    // DDL
    'CREATE', 'ALTER', 'DROP', 'TABLE', 'VIEW', 'INDEX', 'SEQUENCE', 'TRIGGER', 'FUNCTION', 'PROCEDURE',
    'SCHEMA', 'DATABASE', 'EXTENSION', 'TYPE',

    // 连接
    'JOIN', 'INNER JOIN', 'LEFT JOIN', 'RIGHT JOIN', 'FULL JOIN', 'CROSS JOIN', 'NATURAL JOIN', 'ON', 'USING',

    // 条件
    'AND', 'OR', 'NOT', 'IN', 'BETWEEN', 'LIKE', 'ILIKE', 'IS NULL', 'IS NOT NULL', 'EXISTS', 'DISTINCT',

    // 事务
    'BEGIN', 'COMMIT', 'ROLLBACK', 'SAVEPOINT', 'RELEASE SAVEPOINT', 'TRUNCATE',

    // 其他
    'AS', 'CASE', 'WHEN', 'THEN', 'ELSE', 'END', 'WITH', 'RECURSIVE', 'UNION', 'INTERSECT', 'EXCEPT',
    'DEFAULT', 'RETURNING', 'CAST', 'NULL', 'TRUE', 'FALSE'
];

// PostgreSQL 常用聚合函数
const pgAggregateFunctions = [
    'COUNT', 'SUM', 'AVG', 'MIN', 'MAX', 'ARRAY_AGG', 'STRING_AGG'
];

// PostgreSQL 常用字符串函数
const pgStringFunctions = [
    'CONCAT', 'CONCAT_WS', 'SUBSTRING', 'UPPER', 'LOWER', 'TRIM', 'LTRIM', 'RTRIM',
    'REPLACE', 'SPLIT_PART', 'LEFT', 'RIGHT', 'LPAD', 'RPAD', 'FORMAT'
];

// PostgreSQL 常用日期时间函数
const pgDateFunctions = [
    'NOW', 'CURRENT_DATE', 'CURRENT_TIME', 'CURRENT_TIMESTAMP',
    'AGE', 'DATE_PART', 'DATE_TRUNC', 'EXTRACT', 'TO_CHAR', 'TO_DATE'
];

// PostgreSQL 数学函数
const pgMathFunctions = [
    'ABS', 'CEIL', 'CEILING', 'FLOOR', 'ROUND', 'RANDOM', 'POWER', 'MOD', 'GREATEST', 'LEAST'
];

// PostgreSQL JSON/JSONB 常用函数
const pgJsonFunctions = [
    'TO_JSON', 'TO_JSONB', 'ROW_TO_JSON', 'JSON_AGG', 'JSONB_AGG',
    'JSON_BUILD_OBJECT', 'JSONB_BUILD_OBJECT', 'JSON_BUILD_ARRAY', 'JSONB_BUILD_ARRAY',
    'JSON_EXTRACT_PATH_TEXT', 'JSONB_EXTRACT_PATH_TEXT'
];

// select下常用子标签
export const selectChildTags = [
    "if",
    "where",
    "foreach",
    "choose",
    "when",
    "otherwise",
    "set",
    "trim",
    "bind",
];

// 给每个子标签定义常用属性
export const attributesByTag = {
    if: ["test"],
    where: [],
    foreach: ["collection", "item", "index", "open", "close", "separator"],
    choose: [],
    when: ["test"],
    otherwise: [],
    set: [],
    trim: ["prefix", "suffix", "prefixOverrides", "suffixOverrides"],
    bind: ["name", "value"],
};

const sqlKeywords = [
    ...pgKeywords,
    ...pgAggregateFunctions,
    ...pgStringFunctions,
    ...pgDateFunctions,
    ...pgMathFunctions,
    ...pgJsonFunctions
];

function isInsideSelectTag(model, position) {
    const text = model.getValueInRange({
        startLineNumber: 1,
        startColumn: 1,
        endLineNumber: position.lineNumber,
        endColumn: position.column,
    });
    const openTags = (text.match(/<select(\s|>)/g) || []).length;
    const closeTags = (text.match(/<\/select>/g) || []).length;
    return openTags > closeTags;
}


function getInsertTextByTag(tag) {
    const attrs = attributesByTag[tag] || [];
    if (attrs.length === 0) {
        // 无属性，光标放内容区
        return `<${tag}>\$0</${tag}>`;
    } else {
        // 有属性，光标放第一个属性的引号内
        // 例如：<if test="\$1">\$0</if>
        const firstAttr = attrs[0];
        // 其他属性不自动插入，避免复杂
        return `<${tag} ${firstAttr}="\$1">\$0</${tag}>`;
    }
}

// 判断光标是否在标签名后且标签内，例如 <if | 或 <if te|
function isCursorInTagNameOrAttr(model, position) {
    const lineContent = model.getLineContent(position.lineNumber);
    const textBeforeCursor = lineContent.substring(0, position.column - 1); // column 从1开始
    // 判断光标是否在 <tag 后面但未闭合 >
    // 简单判断：最后一个 < 是否有 >，且 < 在最后一个 > 之后
    const lastOpen = textBeforeCursor.lastIndexOf("<");
    const lastClose = textBeforeCursor.lastIndexOf(">");
    return lastOpen > lastClose;
}

// 注册 XML 的 CompletionItemProvider
monaco.languages.registerCompletionItemProvider('xml', {
    triggerCharacters: [" ", "<", ":", "="], // 加入空格触发补全
    provideCompletionItems: (model, position) => {
        // ...此处你的补全代码保持不变...
        if (!isInsideSelectTag(model, position)) {
            return { suggestions: [] };
        }
        const textUntilPosition = model.getValueInRange({
            startLineNumber: 1,
            startColumn: 1,
            endLineNumber: position.lineNumber,
            endColumn: position.column,
        });
        const tagNameMatch = textUntilPosition.match(/<([a-zA-Z0-9]+)([^<>]*)$/);
        const inTag = isCursorInTagNameOrAttr(model, position);

        if (inTag && tagNameMatch) {
            const currentTag = tagNameMatch[1];
            const alreadyTypedAttrs = (tagNameMatch[2] || "")
                .split(/\s+/)
                .map((a) => a.split("=")[0])
                .filter((a) => a.length > 0);
            const possibleAttrs = attributesByTag[currentTag] || [];
            const suggestions = possibleAttrs
                .filter((attr) => !alreadyTypedAttrs.includes(attr))
                .map((attr) => ({
                    label: attr,
                    kind: monaco.languages.CompletionItemKind.Property,
                    insertText: `${attr}="$1"`,
                    insertTextRules:
                        monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
                    documentation: `属性 ${attr}`,
                }));
            return { suggestions };
        } else {
            // 光标在标签外补全select子标签名
            const suggestions = selectChildTags.map((tag) => ({
                label: tag,
                kind: monaco.languages.CompletionItemKind.Snippet,
                insertText: getInsertTextByTag(tag),
                insertTextRules:
                    monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
                documentation: `MyBatis <${tag}> 标签`,
            }));

            // 1️⃣ SQL 关键字
            suggestions.push(
                ...sqlKeywords.map(keyword => ({
                    label: keyword,
                    kind: monaco.languages.CompletionItemKind.Keyword,
                    insertText: keyword,
                    insertTextRules:
                        monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
                    documentation: `SQL 关键字 ${keyword}`,
                }))
            );
            return { suggestions };
        }
    }
});